﻿namespace mPassRT.Common
{
    using System.IO;
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Json;
    using System.Text;
    using System.Threading.Tasks;

    using Windows.Storage;

    public static class SerializationUtility
    {
        public static async Task SerializeToFile<T>(string fileName, T graph) where T : class
        {
            using (
                Stream stream =
                    await
                    ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(
                        fileName, CreationCollisionOption.ReplaceExisting))
            {
                SerializeToStream(stream, graph);
            }
        }

        public static string SerializeToString<T>(T graph) where T : class
        {
            using (var stream = new MemoryStream())
            {
                SerializeToStream(stream, graph);
                byte[] bytes = stream.ToArray();
                return Encoding.UTF8.GetString(bytes, 0, bytes.Length);
            }
        }

        public static async Task<T> DeserializeFromFile<T>(string fileName) where T : class
        {
            Stream stream = null;
            try
            {
                stream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(fileName);
                return DeserializeFromStream<T>(stream);
            }
            catch (IOException)
            {
                // file not found or some other I/O issue
                return null;
            }
            finally
            {
                if (stream != null)
                {
                    stream.Dispose();
                }
            }
        }

        public static T DeserializeFromString<T>(string value) where T : class 
        {
            using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(value)))
            {
                return DeserializeFromStream<T>(stream);
            }
        }

        private static void SerializeToStream<T>(Stream stream, T graph) where T : class
        {
            var serializer = new DataContractJsonSerializer(typeof(T));
            serializer.WriteObject(stream, graph);
        }

        private static T DeserializeFromStream<T>(Stream stream) where T : class
        {
            try
            {
                var serializer = new DataContractJsonSerializer(typeof(T));
                object graph = serializer.ReadObject(stream);
                return graph as T;
            }
            catch (SerializationException)
            {
                // wrong format
                return null;
            }
        }
    }
}
